#ifndef THREADPOOL_H
#define THREADPOOL_H

#include <list>
#include <vector>
#include <cstdio>
#include <exception>
#include <pthread.h>
#include "locker.h"


template<typename T>
class ThreadPool
{
    public:
        ThreadPool(size_t corePoolSize = 4, size_t maximumPoolSize = 8, size_t keepAliveTime = 1000,  size_t queueCapacity = 10000);
        ~ThreadPool();

        bool append(T* request);

    private:
        void cleanup();
        static void* worker(void* arg);
        void run();
    private:
        //thread pool parameter
        size_t corePoolSize;
        size_t maximumPoolSize;
        size_t keepAliveTime;//free thread keep alive time
        size_t queueCapacity;//queue capacity
        std::atomic<bool> stop;//stop flag

        //thread manage
        std::vector<pthread_t> threads;
        std::list<T*> workQueue;

        //synchronized mechanism
        Locker queueLocker;
        Sem queueSem;
};
template<typename T>
void ThreadPool<T>::cleanup()
{
    // Set stop flag
    stop.store(true, std::memory_order_release);
    // Wake up all threads
    for (size_t i = 0; i < threads.size(); ++i) {
        queueSem.post();
    }

    // Clear work queue
    queueLocker.lock();
    workQueue.clear();
    queueLocker.unlock();
}
template<typename T>
ThreadPool<T>::ThreadPool(size_t corePoolSize, size_t maximumPoolSize, size_t keepAliveTime, size_t queueCapacity)
: stop(false)
{
    if (corePoolSize <= 0 || maximumPoolSize <= 0 || 
        corePoolSize > maximumPoolSize ||
        keepAliveTime <= 0 || queueCapacity <= 0) {
        throw std::invalid_argument("Invalid thread pool parameters");
    }
    this->corePoolSize = corePoolSize;
    this->maximumPoolSize = maximumPoolSize;
    this->keepAliveTime = keepAliveTime;
    this->queueCapacity = queueCapacity;


    try {
        // 预留vector空间避免多次分配
        threads.reserve(corePoolSize);
        
        // 创建核心线程
        for (size_t i = 0; i < corePoolSize; ++i) {
            pthread_t tid;
            int ret = pthread_create(&tid, nullptr, worker, this);
            if (ret != 0) {
                throw std::system_error(ret, std::system_category(), 
                                      "Failed to create thread");
            }
            
            // 设置线程为分离状态
            ret = pthread_detach(tid);
            if (ret != 0) {
                pthread_cancel(tid);  // 创建失败则取消线程
                throw std::system_error(ret, std::system_category(),
                                      "Failed to detach thread");
            }
            
            threads.push_back(tid);
        }
    } catch (...) {
        // 创建失败时清理已创建的线程
        cleanup();
        throw;
    }
}

template<typename T>
ThreadPool<T>::~ThreadPool()
{
    cleanup();      
}

//append task to queue
template<typename T>
bool ThreadPool<T>::append(T* request)
{
    queueLocker.lock();
    if (workQueue.size() >= queueCapacity) {
        queueLocker.unlock();
        return false;
    }

    workQueue.push_back(request);
    queueLocker.unlock();
    // have task in queue, wake up a thread to process it
    queueSem.post();
    return true;
}

template<typename T>
void* ThreadPool<T>::worker(void* arg)
{
    ThreadPool* pool = (ThreadPool*)arg;
    pool->run();
    return pool;
}

template<typename T>
void ThreadPool<T>::run() {
    while (!stop.load(std::memory_order_acquire)) {
        // 等待任务
        if (!queueSem.wait()) {
            // fail to wait, maybe threadpool stop
            if (stop.load(std::memory_order_acquire)) break;
            continue;
        }

        // 检查是否应该退出
        if (stop.load(std::memory_order_acquire)) {
            queueSem.post();  // 将信号量传递给其他线程
            break;
        }

        // 从队列获取任务
        T* task = nullptr;
        {
            queueLocker.lock();
            if (!workQueue.empty()) {
                task = workQueue.front();
                workQueue.pop_front();
                queueLocker.unlock();
            }
        }

        // 处理任务
        if (task) {
            try {
                task->process();
            } catch (const std::exception& e) {
                std::cerr << "Task processing error: " << e.what() << std::endl;
            } catch (...) {
                std::cerr << "Unknown task processing error" << std::endl;
            }
            
        }
    }
}
    
#endif // THREADPOOL_H